﻿using ASmile.DBModel;
using ASmile.Extend;
using ASmile.ORM.Cores;
using ASmile.Com.Report;
using System.Collections.Generic;
using System;
using ASmile.Helpers;
using ASmile.Tools;
using System.Data;
using ASmile.ORM.Entitys;

namespace ASmile.Com.Da
{
    public class ReportBLL : BLLCrudBase<ArgGetReport, Sys_ReportArg>, IReportBLL
    {
        protected override void SetQuery(QueryCondition<Sys_ReportArg> query, ArgGetReport arg)
        {
            if (arg.MainId.IsNotEmpty())
            {
                query.WhereAnd(s => s.MainId == arg.MainId);
            }
            if (arg.FormName.IsNotEmpty())
            {
                query.WhereAnd(s => s.MainId == arg.MainId);
            }
            query.OrderBy(s => s.OrderNo);
        }

        protected override ApiResult<string> VerifyModel(Sys_ReportArg model, bool isAdd)
        {
            if (model.FormName.IsEmpty())
            {
                return RetErr("FormName", "窗体名称不能为空");
            }
            if (model.ArgName.IsEmpty())
            {
                return RetErr("ArgName", "参数名称不能为空");
            }
            if (model.ControlType <= 0 || model.ControlTypeName.IsEmpty())
            {
                return RetErr("ControlType", "控件类型不能为空");
            }
            if (isAdd)
            {
                model.Id = NewId();
                return RetOK(model.Id, "新增成功");
            }
            else
            {
                return RetOK(string.Empty, "更新成功");
            }
        }

        /// <summary>
        /// 交换两个行的排序
        /// </summary>
        public ApiResult SwapOrderNo(ArgSwapOrderNo arg)
        {
            if (arg.SrcId.IsEmpty() || arg.SrcId.IsEmpty())
            {
                return RetOK("参数错误");
            }
            Sys_ReportArg model = new Sys_ReportArg();
            model.Id = arg.SrcId;
            model.OrderNo = arg.TarOrderNo;
            DB.Update(model);
            model.Id = arg.TarId;
            model.OrderNo = arg.SrcOrderNo;
            DB.Update(model);
            return RetOK("交换位置成功");
        }
        /// <summary>
        /// 修改指定列的排序
        /// </summary>
        public ApiResult ChangeOrderNo(Sys_ReportArg model)
        {
            if (model.Id.IsEmpty())
            {
                return RetErr("未选中修改的数据");
            }
            model.ClearChangedState();
            model.SetFieldChanged(nameof(model.OrderNo));

            var r = DB.Update(model);
            if (r.RowCount == 1)
            {
                return RetOK("修改成功");
            }
            return RetErr($"修改失败");
        }

        public ApiResultList<Sys_Report> GetReportList(ArgGetReport arg)
        {
            return
            GetPagerList<Sys_Report>(arg, (query) =>
            {
                if (arg.FormName.IsNotEmpty())
                {
                    query.WhereAnd(s => s.FormName == arg.FormName);
                }
                if (arg.SearchVal.IsNotEmpty())
                {
                    string likeStr = arg.SearchValLike;
                    query.WhereAnd(s =>
                        s.WEx_Like(s.FormName, likeStr) ||
                        s.WEx_Like(s.ProcName, likeStr)
                        );
                }
            });
        }

        ApiResult<string> VerifyReport(Sys_Report model, bool isAdd)
        {
            if (model.FormName.IsEmpty())
            {
                return RetErr("FormName", "窗口名称不能为空");
            }
            if (model.ProcName.IsEmpty())
            {
                return RetErr("ProcName", "过程名称不能为空");
            }
            if (DB.QueryExist<Sys_Report>(s => s.FormName == model.FormName && s.Id != model.Id))
            {
                return RetErr("FormName", "窗口配置已经添加");
            }
            if (isAdd)
            {
                model.Id = NewId();
                return RetOK(model.Id, "新增成功");
            }
            else
            {
                return RetOK(string.Empty, "更新成功");
            }
        }

        public ApiResult<string> AddReport(Sys_Report model)
        {
            var ret = VerifyReport(model, true);
            if (!ret) return ret;
            DB.Insert(model);
            return ret;
        }

        public ApiResult<string> EditReport(Sys_Report model)
        {
            var ret = VerifyReport(model, false);
            if (!ret) return ret;
            DB.Update(model);
            return ret;
        }

        public ApiResult DelReport(string id)
        {
            var ret = DB.Delete<Sys_Report>(s => s.Id == id);
            if (ret.RowCount == 0)
            {
                return RetErr("移除失败");
            }
            return RetOK("移除成功");
        }

        /// <summary>
        /// 获取报表窗体的参数
        /// </summary>
        public ApiResult<RetVModel> GetVModel(ArgGetReport arg)
        {
            RetVModel ret = new RetVModel();
            DataCacheCom.GetReport(arg.FormName);
            ret.ReportMain = DB.Query<Sys_Report>(s => s.FormName == arg.FormName).ToEntity();
            if (ret.ReportMain == null)
            {
                return RetErr<RetVModel>("未找到配置");
            }
            ret.ReportArgs =
            GetPagerList<Sys_ReportArg>(0, 0, out _, (query) =>
            {
                query.WhereAnd(s => s.MainId == ret.ReportMain.Id);
                query.OrderBy(s => s.OrderNo);
            });
            if (ret.ReportArgs != null && ret.ReportArgs.Count > 0)
            {
                foreach (var item in ret.ReportArgs)
                {
                    if (item.DataSource.IsEmpty()) continue;

                    SetDataSource(item);
                }
            }
            return RetOK(ret);
        }

        void SetDataSource(Sys_ReportArg arg)
        {
            try
            {
                if (arg.DataSource.IsEmpty()) return;

                if (arg.DataSource.StartsWith("L:"))
                {
                    var rows = arg.DataSource.Substring(2).SplitByNotEmpty(";");
                    arg.DataSourceList = new List<Sys_ReportArg.DataSourceModel>();
                    foreach (var row in rows)
                    {
                        var cols = row.SplitByNotEmpty(",");
                        var m = new Sys_ReportArg.DataSourceModel();
                        m.Val = cols[0];
                        if (cols.Length > 1)
                        {
                            m.Id = cols[1];
                        }
                        else
                        {
                            m.Id = m.Val;
                        }
                        arg.DataSourceList.Add(m);
                    }

                    return;
                }

                if (!arg.DataSource.StartsWith("P:")) return;

                //P:P_GetDeptsByUser(@Type1=1,@Type2=2)
                //arg.DataSource.SplitByNotEmpty
                var strArr = arg.DataSource.SplitByNotEmpty("(", ")");
                var procName = strArr[0].Substring(2);
                Dictionary<string, object> procArgs = new Dictionary<string, object>();
                if (strArr.Length > 1)
                {
                    var argVals = strArr[1].SplitByNotEmpty(",");
                    foreach (var item in argVals)
                    {
                        var val2 = item.SplitByNotEmpty("=");
                        procArgs[val2[0]] = val2[1];
                    }
                }
                //第一列为显示文本，第二个参数为值，如果只有一个参数则表示参数和值一样
                procArgs["CurrUserId"] = CurrUserId;

                arg.DataSourceList = DB.ExecProcedure(procName, procArgs).ToList<Sys_ReportArg.DataSourceModel>();
            }
            catch (Exception ex)
            {
                LogHelper.LogObj.Error("解析公共报表参数数据源异常", ex);
            }
        }

        bool GetProcArgs(ArgReportData arg,
            out Dictionary<string, object> procArgs,
            out P_ReportData pModel,
            out Sys_Report report,
            out string msg)
        {
            procArgs = new Dictionary<string, object>();
            report = DataCacheCom.GetReport(arg.FormName);
            if (report == null)
            {
                pModel = null;
                msg = "报表不存在";
                return false;
            }

            if (report.IsPager)
            {
                pModel = new P_ReportPageData(report.ProcName)
                {
                    PageNo = arg.PageNo,
                    PageSize = arg.PageSize
                };
            }
            else
            {
                pModel = new P_ReportData(report.ProcName);
            }
            pModel.CurrUserId = CurrUserId;
            if (report.IsSearchTxt)
            {
                procArgs["SearchValue"] = arg.SearchValue;
            }
            string reportId = report.Id;
            var reportArgs = DataCacheCom.GetReportArg(s => s.MainId == reportId);
            if (reportArgs != null && reportArgs.Count > 0)
            {
                foreach (var item in arg.ArgList)
                {
                    var rArg = reportArgs.Find(s => s.ArgName == item.Key);
                    if (rArg == null) continue;
                    object val;
                    if (EnumHelper.StringToEnum(rArg.DataType, out EmDataType dataType))
                    {
                        switch (dataType)
                        {
                            case EmDataType.@int:
                                val = Convert.ToInt32(item.Value);
                                break;
                            case EmDataType.@decimal:
                                val = Convert.ToDecimal(item.Value);
                                break;
                            case EmDataType.@bool:
                                val = Convert.ToBoolean(item.Value);
                                break;
                            case EmDataType.datetime:
                                val = Convert.ToDateTime(item.Value);
                                break;
                            case EmDataType.timespan:
                                val = TimeSpan.Parse(item.Value);
                                break;
                            case EmDataType.@string:
                            default:
                                val = item.Value;
                                break;
                        }
                    }
                    else
                    {
                        val = item.Value;
                    }

                    procArgs[item.Key] = val;
                }
            }
            msg = "OK";
            return true;
        }
        /// <summary>
        /// 获取窗体表格的数据
        /// </summary>
        public ApiResult<RetReportData> GetReportData(ArgReportData arg)
        {
            if (!GetProcArgs(arg, out Dictionary<string, object> procArgs, out P_ReportData pModel, out Sys_Report report, out string msg))
            {
                return RetErr<RetReportData>(msg);
            }
            RetReportData rData = new RetReportData();
            var ds = DB.ExecProcedure(pModel, procArgs).ToDataSet();
            if (ds == null || ds.Tables.Count == 0)
            {
                return RetErr<RetReportData>("没有记录或配置错误");
            }

            rData.DetailData = MiniTable.Create(ds.Tables[0]);
            if (report.IsPager && pModel is P_ReportPageData pageModel)
            {
                rData.DetailData.RowTotal = pageModel.Total;
            }
            if (ds.Tables.Count > 1)
            {
                rData.SumInfoList = new List<string>();
                foreach (DataRow item in ds.Tables[1].Rows)
                {
                    rData.SumInfoList.Add($"{item[0]}");
                }
            }

            return RetOK(rData, "OK");
        }
        /// <summary>
        /// 获取打印预览(Grid++)的数据
        /// </summary>
        public ApiResult<RetPrintData> GetPrintData(ArgReportData arg)
        {
            if (!GetProcArgs(arg, out Dictionary<string, object> procArgs, out P_ReportData pModel, out Sys_Report report, out string msg))
            {
                return RetErr<RetPrintData>(msg);
            }

            var data = DB.ExecProcedure(pModel, procArgs).ToDataSet();
            if (data.Tables.Count == 0)
            {
                return RetErr<RetPrintData>("数据为空");
            }
            var detail = MiniTable.Create(data.Tables[0]);
            RetPrintData rData = new RetPrintData
            {
                DetailData = detail,

            };

            if (data.Tables.Count > 1)
            {
                rData.Args = new Dictionary<string, string>();

                for (int i = 1; i < data.Tables.Count; i++)
                {
                    var dt = data.Tables[i];

                    foreach (DataRow row in dt.Rows)
                    {
                        foreach (DataColumn col in dt.Columns)
                        {
                            var val = row[col.ColumnName];
                            if (val == DBNull.Value || val == null) continue;
                            rData.Args[col.ColumnName] = val.ToString();
                        }
                    }

                }
            }
            return RetOK(rData, "OK");
        }

        class P_ReportData : ProcEntityBase
        {
            public P_ReportData(string procName)
            {
                ProcedureName = procName;
            }
            /// <summary>
            /// 当前用户Id
            /// </summary>
            public string CurrUserId { set; get; }
        }

        class P_ReportPageData : P_ReportData
        {
            public P_ReportPageData(string procName) : base(procName)
            { }

            /// <summary>
            /// 当前页
            /// </summary>
            public int PageNo { set; get; }
            /// <summary>
            /// 页大小
            /// </summary>
            public int PageSize { set; get; }
            /// <summary>
            /// 分页时返回的记录总数
            /// </summary>
            [ProcParam(ParameterDirection.Output)]
            public int Total { set; get; }
        }
    }
}